package test.excel.config;

import java.io.File;
import java.io.InputStream;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

public class ConfigParser {
    private Unmarshaller unmarshaller;

    public ConfigParser() {
        try {
            unmarshaller = JAXBContext.newInstance(FileImportConfig.class).createUnmarshaller();

            SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI );

            Schema schema = factory.newSchema(this.getClass().getResource("/parser.xsd"));

            unmarshaller.setSchema(schema);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public FileImportConfig parse(File file) {
        try {
            FileImportConfig config = (FileImportConfig) unmarshaller.unmarshal(file);

            validate(config);

            return config;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public FileImportConfig parse(InputStream in) {
        try {
            FileImportConfig config = (FileImportConfig) unmarshaller.unmarshal(in);

            validate(config);

            return config;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void validate(FileImportConfig config) {
        for (int i = 0; i < config.getSheets().size(); i++) {
            SheetConfig sheetConfig = config.getSheets().get(i);

            if (sheetConfig.getIndex() == null && sheetConfig.getSheetName() == null) {
                throw new IllegalStateException("Invalid config. The sheet should have at least a name or index. Filename: " + config.getName() + ". Sheet number in config: " + i);
            }

            for (int j = 0; j < sheetConfig.getColumns().size(); j++) {
                ColumnConfig columnConfig = sheetConfig.getColumns().get(j);

                if (columnConfig.getIndex() == null && columnConfig.getSheetColName() == null) {
                    throw new IllegalStateException("Invalid config. The column should have at least a name or index. Filename: " + config.getName() + ". Sheet number in config: " + i + ", col number in config: " + j);
                }
            }

            if (!sheetConfig.isHeader()) {
                for (int j = 0; j < sheetConfig.getColumns().size(); j++) {
                    ColumnConfig columnConfig = sheetConfig.getColumns().get(j);

                    if (columnConfig.getIndex() == null) {
                        throw new IllegalStateException("Invalid config. The column should have an index when header is not defined. Filename: " + config.getName() + ". Sheet number in config: " + i + ", col number in config: " + j);
                    }
                }
            }
        }
    }
}
